<div class="content-section introduction">
    <div class="feature-intro">
        <h1>TreeSelect</h1>
        <p>TreeSelect is a form component to choose from hierarchical data.</p>
    </div>
    <app-demoActions github="treeselect" stackblitz="treeselect-demo"></app-demoActions>
</div>

<div class="content-section implementation">
    <div class="card">
        <h5>Single</h5>
        <p-treeSelect [(ngModel)]="selectedNode" [options]="nodes1" placeholder="Select Item"></p-treeSelect>

        <h5>Multiple</h5>
        <p-treeSelect [(ngModel)]="selectedNodes1" [options]="nodes2" [metaKeySelection]="false" selectionMode="multiple" placeholder="Select Item"></p-treeSelect>

        <h5>Checkbox</h5>
        <p-treeSelect [(ngModel)]="selectedNodes2" [options]="nodes3" display="chip" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"></p-treeSelect>

        <h5>Filter</h5>
        <p-treeSelect [(ngModel)]="selectedNodes3" [options]="nodes4" [filter]="true" [filterInputAutoFocus]="true" [resetFilterOnHide]="false" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"></p-treeSelect>
    </div>
</div>

<div class="content-section documentation">
    <p-tabView>
        <p-tabPanel header="Documentation">
            <h5>Import</h5>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
import &#123;TreeSelectModule&#125; from 'primeng/treeselect';
</app-code>
            <h5>Getting Started</h5>
		    <p>TreeSelect component requires an array of TreeNode objects as its <i>options</i> and keys of the nodes as its value.</p>
<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;p-treeSelect [(ngModel)]="selectedNode" [options]="nodes" placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;
</app-code>

<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
export class TreeSelectDemoComponent implements OnInit &#123;
    nodes: any[];

    selectedNode: any;
    constructor(public nodeService: NodeService) &#123; &#125;

    ngOnInit() &#123;
        this.nodeService.getFiles().then(files => this.nodes1 = files);
    &#125;
&#125;
</app-code>

            <p>In example below, nodes are retrieved from a remote data source.</p>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
&#123;
    "data":
    [
        &#123;
            "label": "Documents",
            "data": "Documents Folder",
            "expandedIcon": "pi pi-folder-open",
            "collapsedIcon": "pi pi-folder",
            "children": [&#123;
                    "label": "Work",
                    "data": "Work Folder",
                    "expandedIcon": "pi pi-folder-open",
                    "collapsedIcon": "pi pi-folder",
                    "children": [&#123;"label": "Expenses.doc", "icon": "pi pi-file", "data": "Expenses Document"&#125;, &#123;"label": "Resume.doc", "icon": "pi pi-file", "data": "Resume Document"&#125;]
                &#125;,
                &#123;
                    "label": "Home",
                    "data": "Home Folder",
                    "expandedIcon": "pi pi-folder-open",
                    "collapsedIcon": "pi pi-folder",
                    "children": [&#123;"label": "Invoices.txt", "icon": "pi pi-file", "data": "Invoices for this month"&#125;]
                &#125;]
        &#125;,
        &#123;
            "label": "Pictures",
            "data": "Pictures Folder",
            "expandedIcon": "pi pi-folder-open",
            "collapsedIcon": "pi pi-folder",
            "children": [
                &#123;"label": "barcelona.jpg", "icon": "pi pi-image", "data": "Barcelona Photo"&#125;,
                &#123;"label": "logo.jpg", "icon": "pi pi-file", "data": "PrimeFaces Logo"&#125;,
                &#123;"label": "primeui.png", "icon": "pi pi-image", "data": "PrimeUI Logo"&#125;]
        &#125;,
        &#123;
            "label": "Movies",
            "data": "Movies Folder",
            "expandedIcon": "pi pi-folder-open",
            "collapsedIcon": "pi pi-folder",
            "children": [&#123;
                    "label": "Al Pacino",
                    "data": "Pacino Movies",
                    "children": [&#123;"label": "Scarface", "icon": "pi pi-video", "data": "Scarface Movie"&#125;, &#123;"label": "Serpico", "icon": "pi pi-file-video", "data": "Serpico Movie"&#125;]
                &#125;,
                &#123;
                    "label": "Robert De Niro",
                    "data": "De Niro Movies",
                    "children": [&#123;"label": "Goodfellas", "icon": "pi pi-video", "data": "Goodfellas Movie"&#125;, &#123;"label": "Untouchables", "icon": "pi pi-video", "data": "Untouchables Movie"&#125;]
                &#125;]
        &#125;
    ]
&#125;
</app-code>

            <h5>TreeNode API utilized by the TreeSelect</h5>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Type</th>
                            <th>Default</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>label</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Label of the node.</td>
                        </tr>
                        <tr>
                            <td>data</td>
                            <td>any</td>
                            <td>null</td>
                            <td>Data represented by the node.</td>
                        </tr>
                        <tr>
                            <td>icon</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Icon of the node to display next to content.</td>
                        </tr>
                        <tr>
                            <td>expandedIcon</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Icon to use in expanded state.</td>
                        </tr>
                        <tr>
                            <td>collapsedIcon</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Icon to use in collapsed state.</td>
                        </tr>
                        <tr>
                            <td>children</td>
                            <td>TreeNode[]</td>
                            <td>null</td>
                            <td>An array of treenodes as children.</td>
                        </tr>
                        <tr>
                            <td>leaf</td>
                            <td>boolean</td>
                            <td>null</td>
                            <td>Specifies if the node has children. Used in lazy loading.</td>
                        </tr>
                        <tr>
                            <td>style</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Inline style of the node.</td>
                        </tr>
                        <tr>
                            <td>styleClass</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Style class of the node.</td>
                        </tr>
                        <tr>
                            <td>expanded</td>
                            <td>boolean</td>
                            <td>null</td>
                            <td>Whether the node is in an expanded or collapsed state.</td>
						</tr>
                        <tr>
                            <td>type</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Type of the node to match ng-template type.</td>
                        </tr>
                        <tr>
                            <td>parent</td>
                            <td>TreeNode</td>
                            <td>null</td>
                            <td>Parent of the node.</td>
                        </tr>
                        <tr>
                            <td>draggable</td>
                            <td>boolean</td>
                            <td>null</td>
                            <td>Whether to disable dragging for a particular node even if draggableNodes is enabled.</td>
                        </tr>
                        <tr>
                            <td>droppable</td>
                            <td>boolean</td>
                            <td>null</td>
                            <td>Whether to disable dropping for a particular node even if droppableNodes is enabled.</td>
                        </tr>
                        <tr>
                            <td>selectable</td>
                            <td>boolean</td>
                            <td>null</td>
                            <td>Used to disable selection of a particular node.</td>
                        </tr>
                        <tr>
                            <td>key</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Unique key of the node.(<a href="https://github.com/primefaces/primeng/issues/7237#issue-409791407" target="_blank" rel="noopener noreferrer">more</a>)</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h5>Selection Mode</h5>
            <p>TreeSelects offers "single", "multiple" and "checkbox" alternatives for the selection behavior that is defined by the <i>selectionMode</i> option.</p>

<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;p-treeSelect [(ngModel)]="selectedValue1" [options]="nodes" selectionMode="single"  placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;

&lt;p-treeSelect [(ngModel)]="selectedValue2" selectionMode="multiple" [options]="nodes" placeholder="Select Items"&gt;&lt;/p-treeSelect&gt;

&lt;p-treeSelect [(ngModel)]="selectedValue3" selectionMode="checkbox" [options]="nodes" placeholder="Select Items"&gt;&lt;/p-treeSelect&gt;
</app-code>

            <p>In multiple mode or checkbox mode, selection property should be an array. In multiple mode, items can either be selected
                using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled
                devices metaKeySelection is turned off automatically. In checkbox mode, when inititing a tree with preselections, also set partialSelected
                property on node so that minus icon can be displayed when necessary.</p>

            <h5>Chips Display</h5>
            <p>A comma separated list is used by default to display selected items whereas alternative chip mode is provided using the <i>display</i> property to visualize the items as tokens.</p>

<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;p-treeSelect [(ngModel)]="selectedValue" selectionMode="multiple" display="chip" [options]="nodes" placeholder="Select Items"&gt;&lt;/p-treeSelect&gt;
</app-code>

            <h5>Templating</h5>
            <p>Label of an option is used as the display text of an item by default, for custom content support define a <i>value</i> template that gets the selected nodes as a parameter.
                In addition <i>header</i>, <i>footer</i> and <i>empty</i> slots are provided for further customization.</p>
<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;p-treeSelect [(ngModel)]="selectedValue2" selectionMode="multiple" [options]="nodes" placeholder="Select Items"&gt;
    &lt;ng-template pTemplate="value"&gt;
        Custom Content
    &lt;/ng-template&gt;
&lt;/p-treeSelect&gt;
</app-code>

            <h5>Properties</h5>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Type</th>
                            <th>Default</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>options</td>
                            <td>array</td>
                            <td>null</td>
                            <td>An array of treenodes.</td>
                        </tr>
                        <tr>
                            <td>scrollHeight</td>
                            <td>string</td>
                            <td>400px</td>
                            <td>Height of the viewport, a scrollbar is defined if height of list exceeds this value.</td>
                        </tr>
                        <tr>
                            <td>placeholder</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Label to display when there are no selections.</td>
                        </tr>
                        <tr>
                            <td>disabled</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When present, it specifies that the component should be disabled.</td>
                        </tr>
                        <tr>
                            <td>tabindex</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Index of the element in tabbing order.</td>
                        </tr>
                        <tr>
                            <td>inputId</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Identifier of the underlying input element.</td>
                        </tr>
                        <tr>
                            <td>ariaLabelledBy</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Establishes relationships between the component and label(s) where its value should be one or more element IDs.</td>
                        </tr>
                        <tr>
                            <td>selectionMode</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Defines the selection mode, valid values "single", "multiple", and "checkbox".</td>
                        </tr>
                        <tr>
                            <td>panelClass</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Style class of the overlay panel.</td>
                        </tr>
                        <tr>
                            <td>appendTo</td>
                            <td>string</td>
                            <td>body</td>
                            <td>A valid query selector or an HTMLElement to specify where the overlay gets attached. Special keywords are "body" for document body
                            and "self" for the element itself.</td>
                        </tr>
                        <tr>
                            <td>emptyMessage</td>
                            <td>string</td>
                            <td>No results found</td>
                            <td>Text to display when there are no options available. Defaults to value from PrimeVue locale configuration.</td>
                        </tr>
                        <tr>
                            <td>display</td>
                            <td>string</td>
                            <td>comma</td>
                            <td>Defines how the selected items are displayed, valid values are "comma" and "chip".</td>
                        </tr>
                        <tr>
                            <td>propagateSelectionUp</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Whether checkbox selections propagate to ancestor nodes.</td>
                        </tr>
                        <tr>
                            <td>propagateSelectionDown</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Whether checkbox selections propagate to descendant nodes.</td>
                        </tr>
                         <tr>
                            <td>metaKeySelection</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item
                                can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.</td>
                        </tr>
                        <tr>
                            <td>filter</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When specified, displays an input field to filter the items.</td>
                        </tr>
                        <tr>
                            <td>filterBy</td>
                            <td>string</td>
                            <td>label</td>
                            <td>When filtering is enabled, filterBy decides which field or fields (comma separated) to search against.</td>
                        </tr>
                        <tr>
                            <td>filterMode</td>
                            <td>string</td>
                            <td>lenient</td>
                            <td>Mode for filtering valid values are "lenient" and "strict". Default is lenient.</td>
                        </tr>
                        <tr>
                            <td>filterPlaceholder</td>
                            <td>string</td>
                            <td>null</td>
                            <td>Placeholder text to show when filter input is empty.</td>
                        </tr>
                        <tr>
                            <td>filterLocale</td>
                            <td>string</td>
                            <td>undefined</td>
                            <td>Locale to use in filtering. The default locale is the host environment's current locale.</td>
                        </tr>
                        <tr>
                            <td>resetFilterOnHide</td>
                            <td>boolean</td>
                            <td>true</td>
                            <td>Clears the filter value when hiding the dropdown.</td>
                        </tr>
                        <tr>
                            <td>showClear</td>
                            <td>boolean</td>
                            <td>false</td>
                            <td>When enabled, a clear icon is displayed to clear the value.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h5>Events</h5>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Parameters</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>onShow</td>
                            <td>-</td>
                            <td>Callback to invoke when the overlay is shown.</td>
                        </tr>
                        <tr>
                            <td>onHide</td>
                            <td>-</td>
                            <td>Callback to invoke when the overlay is hidden.</td>
                        </tr>
                        <tr>
                            <td>onFilter</td>
                            <td>event.filter: Filter value used in filtering.<br>
                                event.filteredValue: Filtered data after running the filtering.</td>
                            <td>Callback to invoke when data is filtered.</td>
                        </tr>
                        <tr>
                            <td>onNodeSelect</td>
                            <td>node: Node instance</td>
                            <td>Callback to invoke when a node is selected.</td>
                        </tr>
                        <tr>
                            <td>onNodeUnselect</td>
                            <td>node: Node instance</td>
                            <td>Callback to invoke when a node is unselected.</td>
                        </tr>
                        <tr>
                            <td>onNodeExpand</td>
                            <td>node: Node instance</td>
                            <td>Callback to invoke when a node is expanded.</td>
                        </tr>
                        <tr>
                            <td>onNodeCollapse</td>
                            <td>node: Node instance</td>
                            <td>Callback to invoke when a node is collapsed.</td>
                        </tr>
                        <tr>
                            <td>onClear</td>
                            <td>-</td>
                            <td>Callback to invoke when input field is cleared.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h5>Templates</h5>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Parameters</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>value</td>
                            <td>$implicit: Value of the component</td>
                        </tr>
                        <tr>
                            <td>header</td>
                            <td>$implicit: Value of the component <br />
                                options: TreeNode options</td>
                        </tr>
                        <tr>
                            <td>footer</td>
                            <td>$implicit: Value of the component <br />
                               options: TreeNode options</td>
                        </tr>
                        <tr>
                            <td>empty</td>
                            <td>-</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h5>Styling</h5>
            <p>Following is the list of structural style classes, for theming classes visit <a href="#" [routerLink]="['/theming']">theming</a> page.</p>
            <div class="doc-tablewrapper">
                <table class="doc-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Element</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>p-treeselect</td>
                            <td>Container element.</td>
                        </tr>
                        <tr>
                            <td>p-treeselect-label-container</td>
                            <td>Container of the label to display selected items.</td>
                        </tr>
                        <tr>
                            <td>p-treeselect-label</td>
                            <td>Label to display selected items.</td>
                        </tr>
                        <tr>
                            <td>p-treeselect-trigger</td>
                            <td>Dropdown button.</td>
                        </tr>
                        <tr>
                            <td>p-treeselect-panel</td>
                            <td>Overlay panel for items.</td>
                        </tr>
                        <tr>
                            <td>p-treeselect-items-wrapper</td>
                            <td>List container of items.</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <h5>Dependencies</h5>
            <p>None.</p>
        </p-tabPanel>

        <p-tabPanel header="Source">
            <a href="https://github.com/primefaces/primeng/tree/master/src/app/showcase/components/treeselect" class="btn-viewsource" target="_blank">
                <span>View on GitHub</span>
            </a>
            <a href="https://stackblitz.com/edit/primeng-treeselect-demo" class="btn-viewsource" style="margin-left: .5em;" target="_blank">
                <span>Edit in StackBlitz</span>
            </a>

<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;h5&gt;Single&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNode" [options]="nodes1" placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;

&lt;h5&gt;Multiple&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNodes1" [options]="nodes2" [metaKeySelection]="false" selectionMode="multiple" placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;

&lt;h5&gt;Checkbox&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNodes2" [options]="nodes3" display="chip" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item"&gt;&lt;/p-treeSelect&gt;

&lt;h5&gt;Filter&lt;/h5&gt;
&lt;p-treeSelect [(ngModel)]="selectedNodes3" [options]="nodes4" [metaKeySelection]="false" selectionMode="checkbox" placeholder="Select Item" [filter]="true" [filterInputAutoFocus]="true"&gt;&lt;/p-treeSelect&gt;
</app-code>
<app-code lang="typescript" ngNonBindable ngPreserveWhitespaces>
export class TreeSelectModule &#123;
    nodes1: any[];

    nodes2: any[];

    nodes3: any[];

    nodes4: any[];

    selectedNodes1: any[] = [];

    selectedNodes2: any[] = [];

    selectedNode: any;

    constructor(public nodeService: NodeService) &#123; &#125;

    ngOnInit() &#123;
        this.nodeService.getFiles().then(files => this.nodes1 = files);
        this.nodeService.getFiles().then(files => this.nodes2 = files);
        this.nodeService.getFiles().then(files => this.nodes3 = files);
        this.nodeService.getFiles().then(files => this.nodes4 = files);
    &#125;
&#125;
</app-code>
        </p-tabPanel>
        <p-tabPanel header="StackBlitz">
            <ng-template pTemplate="content">
                <iframe src="https://stackblitz.com/edit/primeng-treeselect-demo?embed=1" style="width: 100%; height: 768px; border: none;"></iframe>
            </ng-template>
        </p-tabPanel>
    </p-tabView>
</div>
